#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <dlfcn.h>
#include <unistd.h>

typedef void *(*AlgoConvertFunction)();

typedef void *(*GetSimInstanceFunction)();
typedef int   (*AlgoInitFunction)(void *, const char *);
typedef void *(*AlgoSimFunction)(void *, const char *);
typedef bool *(*AlgoStatusFunction)(void *);
typedef void *(*AlgoStepFunction)(void *);
typedef void *(*AlgoStopFunction)(void *);


int simulate(const char* algo_name, const char* rpusim_lib_path, const char* algo_work_path){
  //librpusim.so调用过程
  if (1)
  {   
      //so的重复load&close
      for (int i = 0; i < 1; i++)
      {
          // 0 open so
          void *hDll = dlopen(rpusim_lib_path, RTLD_LAZY);
          if (!hDll)
          {
              fprintf(stderr, "Could not load the library:%s\r\n", dlerror());
              return 1;
          }

          // 1 get_sim_instance
          GetSimInstanceFunction get_sim_instance = (GetSimInstanceFunction)dlsym(hDll, "get_sim_instance");
          if (!get_sim_instance)
          {
              fprintf(stderr, "Could not locate the function:%s\n", dlerror());
              dlclose(hDll);
              return 1;
          }
          void *sim_instance = get_sim_instance();

          // 2 algo_init
          AlgoInitFunction algo_init = (AlgoInitFunction)dlsym(hDll, "algo_init");
          if (!algo_init)
          {
              fprintf(stderr, "Could not locate the function:%s\n", dlerror());
              dlclose(hDll);
              return 1;
          }
          int error = algo_init(sim_instance, algo_work_path);
          if (error == -1)
          {
              //fprintf(stderr, "Could not locate the function:%s\n", dlerror());
              dlclose(hDll);
              return 1;
          }

          // 3 algo_sim
          AlgoSimFunction algo_sim = (AlgoSimFunction)dlsym(hDll, "algo_sim");
          if (!algo_sim)
          {
              fprintf(stderr, "Could not locate the function:%s\n", dlerror());
              dlclose(hDll);
              return 1;
          }
          //algo_name仅支持aes sm3 md5 sha1
          algo_sim(sim_instance, algo_name);

          // 4 algo_status：true是仿真结束
          AlgoStatusFunction algo_status = (AlgoStatusFunction)dlsym(hDll, "algo_status");
          if (!algo_status)
          {
              fprintf(stderr, "Could not locate the function:%s\n", dlerror());
              dlclose(hDll);
              return 1;
          }
          bool bSimDone = false;

          // 5 algo_step：单步 1SC_NS
          AlgoStepFunction algo_step = (AlgoStepFunction)dlsym(hDll, "algo_step");
          if (!algo_step)
          {
              fprintf(stderr, "Could not locate the function:%s\n", dlerror());
              dlclose(hDll);
              return 1;
          }
          if(1)
          {
              int iCount = 0;//2207 3049 4207 4859
              while(1)
              {
                  bSimDone = algo_status(sim_instance);
                  if(!bSimDone)
                  {
                      algo_step(sim_instance);
                      iCount++;
                  }
                  else
                      break;//算法仿真结束

                  if(iCount == 5000)
                      break;
              }
            //   printf("Step counts: %d\n", iCount);
          }

          // 6 algo_stop
          AlgoStopFunction algo_stop = (AlgoStopFunction)dlsym(hDll, "algo_stop");
          if (!algo_stop)
          {
              fprintf(stderr, "Could not locate the function:%s\n", dlerror());
              dlclose(hDll);
              return 1;
          }
          //必须调用，防止内存泄漏
          algo_stop(sim_instance);

          // 7 dll close
          //必须调用，防止内存泄漏
          dlclose(hDll);
      }
  }
  return 0;
}

int main(int argc, char *argv[]) {
    return simulate(argv[1], argv[2], argv[3]);
}